﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.Texture2DArray
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Bindings;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Internal;
using UnityEngine.Scripting;

#nullable disable
namespace UnityEngine
{
  /// <summary>
  ///   <para>Class for handling 2D texture arrays.</para>
  /// </summary>
  [NativeHeader("Runtime/Graphics/Texture2DArray.h")]
  public sealed class Texture2DArray : Texture
  {
    /// <summary>
    ///   <para>Read Only. This property is used as a parameter in some overloads of the CommandBuffer.Blit, Graphics.Blit, CommandBuffer.SetRenderTarget, and Graphics.SetRenderTarget methods to indicate that all texture array slices are bound. The value of this property is -1.</para>
    /// </summary>
    public static extern int allSlices { [NativeName("GetAllTextureLayersIdentifier"), MethodImpl(MethodImplOptions.InternalCall)] get; }

    /// <summary>
    ///   <para>Number of elements in a texture array (Read Only).</para>
    /// </summary>
    public extern int depth { [NativeName("GetTextureLayerCount"), MethodImpl(MethodImplOptions.InternalCall)] get; }

    /// <summary>
    ///   <para>Texture format (Read Only).</para>
    /// </summary>
    public extern TextureFormat format { [NativeName("GetTextureFormat"), MethodImpl(MethodImplOptions.InternalCall)] get; }

    public override extern bool isReadable { [MethodImpl(MethodImplOptions.InternalCall)] get; }

    [FreeFunction("Texture2DArrayScripting::Create")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool Internal_CreateImpl(
      [Writable] Texture2DArray mono,
      int w,
      int h,
      int d,
      int mipCount,
      GraphicsFormat format,
      TextureColorSpace colorSpace,
      TextureCreationFlags flags);

    private static void Internal_Create(
      [Writable] Texture2DArray mono,
      int w,
      int h,
      int d,
      int mipCount,
      GraphicsFormat format,
      TextureColorSpace colorSpace,
      TextureCreationFlags flags)
    {
      if (!Texture2DArray.Internal_CreateImpl(mono, w, h, d, mipCount, format, colorSpace, flags))
        throw new UnityException("Failed to create 2D array texture because of invalid parameters.");
    }

    [FreeFunction(Name = "Texture2DArrayScripting::Apply", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void ApplyImpl(bool updateMipmaps, bool makeNoLongerReadable);

    /// <summary>
    ///   <para>Gets the pixel color data for a mipmap level of a slice as Color structs.</para>
    /// </summary>
    /// <param name="arrayElement">The array slice to read pixel data from.</param>
    /// <param name="miplevel">The mipmap level to get. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    /// <returns>
    ///   <para>An array that contains the pixel colors.</para>
    /// </returns>
    [FreeFunction(Name = "Texture2DArrayScripting::GetPixels", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern Color[] GetPixels(int arrayElement, int miplevel);

    /// <summary>
    ///   <para>Gets the pixel color data for a mipmap level of a slice as Color structs.</para>
    /// </summary>
    /// <param name="arrayElement">The array slice to read pixel data from.</param>
    /// <param name="miplevel">The mipmap level to get. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    /// <returns>
    ///   <para>An array that contains the pixel colors.</para>
    /// </returns>
    public Color[] GetPixels(int arrayElement) => this.GetPixels(arrayElement, 0);

    [FreeFunction(Name = "Texture2DArrayScripting::SetPixelDataArray", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern bool SetPixelDataImplArray(
      Array data,
      int mipLevel,
      int element,
      int elementSize,
      int dataArraySize,
      int sourceDataStartIndex = 0);

    [FreeFunction(Name = "Texture2DArrayScripting::SetPixelData", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern bool SetPixelDataImpl(
      IntPtr data,
      int mipLevel,
      int element,
      int elementSize,
      int dataArraySize,
      int sourceDataStartIndex = 0);

    /// <summary>
    ///   <para>Gets the pixel color data for a mipmap level of a slice as Color32 structs.</para>
    /// </summary>
    /// <param name="arrayElement">The array slice to read pixel data from.</param>
    /// <param name="miplevel">The mipmap level to get. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    /// <returns>
    ///   <para>An array that contains the pixel colors.</para>
    /// </returns>
    [FreeFunction(Name = "Texture2DArrayScripting::GetPixels32", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern Color32[] GetPixels32(int arrayElement, int miplevel);

    /// <summary>
    ///   <para>Gets the pixel color data for a mipmap level of a slice as Color32 structs.</para>
    /// </summary>
    /// <param name="arrayElement">The array slice to read pixel data from.</param>
    /// <param name="miplevel">The mipmap level to get. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    /// <returns>
    ///   <para>An array that contains the pixel colors.</para>
    /// </returns>
    public Color32[] GetPixels32(int arrayElement) => this.GetPixels32(arrayElement, 0);

    /// <summary>
    ///   <para>Sets the pixel colors of an entire mipmap level of a slice.</para>
    /// </summary>
    /// <param name="colors">The array of pixel colours to use. This is a 2D image flattened to a 1D array.</param>
    /// <param name="arrayElement">The array slice to write to.</param>
    /// <param name="miplevel">The mipmap level to write colors to. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    [FreeFunction(Name = "Texture2DArrayScripting::SetPixels", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void SetPixels([Unmarshalled] Color[] colors, int arrayElement, int miplevel);

    /// <summary>
    ///   <para>Sets the pixel colors of an entire mipmap level of a slice.</para>
    /// </summary>
    /// <param name="colors">The array of pixel colours to use. This is a 2D image flattened to a 1D array.</param>
    /// <param name="arrayElement">The array slice to write to.</param>
    /// <param name="miplevel">The mipmap level to write colors to. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    public void SetPixels(Color[] colors, int arrayElement)
    {
      this.SetPixels(colors, arrayElement, 0);
    }

    /// <summary>
    ///   <para>Sets the pixel colors of an entire mipmap level of a slice.</para>
    /// </summary>
    /// <param name="colors">The array of pixel colours to use. This is a 2D image flattened to a 1D array.</param>
    /// <param name="arrayElement">The array slice to write colors to.</param>
    /// <param name="miplevel">The mipmap level to write colors to. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    [FreeFunction(Name = "Texture2DArrayScripting::SetPixels32", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void SetPixels32([Unmarshalled] Color32[] colors, int arrayElement, int miplevel);

    /// <summary>
    ///   <para>Sets the pixel colors of an entire mipmap level of a slice.</para>
    /// </summary>
    /// <param name="colors">The array of pixel colours to use. This is a 2D image flattened to a 1D array.</param>
    /// <param name="arrayElement">The array slice to write colors to.</param>
    /// <param name="miplevel">The mipmap level to write colors to. The range is 0 through the texture's Texture.mipmapCount. The default value is 0.</param>
    public void SetPixels32(Color32[] colors, int arrayElement)
    {
      this.SetPixels32(colors, arrayElement, 0);
    }

    private AtomicSafetyHandle GetSafetyHandleForSlice(int mipLevel, int element)
    {
      AtomicSafetyHandle ret;
      this.GetSafetyHandleForSlice_Injected(mipLevel, element, out ret);
      return ret;
    }

    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern IntPtr GetImageDataPointer();

    internal bool ValidateFormat(TextureFormat format, int width, int height)
    {
      bool flag = this.ValidateFormat(format);
      if (flag && TextureFormat.PVRTC_RGB2 <= format && format <= TextureFormat.PVRTC_RGBA4 && (width != height || !Mathf.IsPowerOfTwo(width)))
        throw new UnityException(string.Format("'{0}' demands texture to be square and have power-of-two dimensions", (object) format.ToString()));
      return flag;
    }

    internal bool ValidateFormat(GraphicsFormat format, int width, int height)
    {
      bool flag = this.ValidateFormat(format, FormatUsage.Sample);
      if (flag && GraphicsFormatUtility.IsPVRTCFormat(format) && (width != height || !Mathf.IsPowerOfTwo(width)))
        throw new UnityException(string.Format("'{0}' demands texture to be square and have power-of-two dimensions", (object) format.ToString()));
      return flag;
    }

    [ExcludeFromDocs]
    public Texture2DArray(
      int width,
      int height,
      int depth,
      DefaultFormat format,
      TextureCreationFlags flags)
      : this(width, height, depth, SystemInfo.GetGraphicsFormat(format), flags)
    {
    }

    [ExcludeFromDocs]
    [RequiredByNativeCode]
    public Texture2DArray(
      int width,
      int height,
      int depth,
      GraphicsFormat format,
      TextureCreationFlags flags)
      : this(width, height, depth, format, flags, Texture.GenerateAllMips)
    {
    }

    [ExcludeFromDocs]
    public Texture2DArray(
      int width,
      int height,
      int depth,
      GraphicsFormat format,
      TextureCreationFlags flags,
      int mipCount)
    {
      if (!this.ValidateFormat(format, width, height))
        return;
      Texture2DArray.ValidateIsNotCrunched(flags);
      Texture2DArray.Internal_Create(this, width, height, depth, mipCount, format, this.GetTextureColorSpace(format), flags);
    }

    /// <summary>
    ///   <para>Create a new texture array.</para>
    /// </summary>
    /// <param name="width">Width of texture array in pixels.</param>
    /// <param name="height">Height of texture array in pixels.</param>
    /// <param name="depth">Number of elements in the texture array.</param>
    /// <param name="linear">Does the texture contain non-color data (i.e. don't do any color space conversions when sampling)? Default is false.</param>
    /// <param name="textureFormat">Format of the texture.</param>
    /// <param name="mipChain">Should mipmaps be created?</param>
    /// <param name="mipCount">Amount of mips to allocate for the texture array.</param>
    public Texture2DArray(
      int width,
      int height,
      int depth,
      TextureFormat textureFormat,
      int mipCount,
      bool linear)
    {
      if (!this.ValidateFormat(textureFormat, width, height))
        return;
      GraphicsFormat graphicsFormat = GraphicsFormatUtility.GetGraphicsFormat(textureFormat, !linear);
      TextureCreationFlags flags = mipCount != 1 ? TextureCreationFlags.MipChain : TextureCreationFlags.None;
      if (GraphicsFormatUtility.IsCrunchFormat(textureFormat))
        flags |= TextureCreationFlags.Crunch;
      Texture2DArray.ValidateIsNotCrunched(flags);
      Texture2DArray.Internal_Create(this, width, height, depth, mipCount, graphicsFormat, this.GetTextureColorSpace(linear), flags);
    }

    /// <summary>
    ///   <para>Create a new texture array.</para>
    /// </summary>
    /// <param name="width">Width of texture array in pixels.</param>
    /// <param name="height">Height of texture array in pixels.</param>
    /// <param name="depth">Number of elements in the texture array.</param>
    /// <param name="linear">Does the texture contain non-color data (i.e. don't do any color space conversions when sampling)? Default is false.</param>
    /// <param name="textureFormat">Format of the texture.</param>
    /// <param name="mipChain">Should mipmaps be created?</param>
    /// <param name="mipCount">Amount of mips to allocate for the texture array.</param>
    public Texture2DArray(
      int width,
      int height,
      int depth,
      TextureFormat textureFormat,
      bool mipChain,
      [DefaultValue("false")] bool linear)
      : this(width, height, depth, textureFormat, mipChain ? -1 : 1, linear)
    {
    }

    /// <summary>
    ///   <para>Create a new texture array.</para>
    /// </summary>
    /// <param name="width">Width of texture array in pixels.</param>
    /// <param name="height">Height of texture array in pixels.</param>
    /// <param name="depth">Number of elements in the texture array.</param>
    /// <param name="linear">Does the texture contain non-color data (i.e. don't do any color space conversions when sampling)? Default is false.</param>
    /// <param name="textureFormat">Format of the texture.</param>
    /// <param name="mipChain">Should mipmaps be created?</param>
    /// <param name="mipCount">Amount of mips to allocate for the texture array.</param>
    [ExcludeFromDocs]
    public Texture2DArray(
      int width,
      int height,
      int depth,
      TextureFormat textureFormat,
      bool mipChain)
      : this(width, height, depth, textureFormat, mipChain ? -1 : 1, false)
    {
    }

    /// <summary>
    ///   <para>Copies changes you've made in a CPU texture to the GPU.</para>
    /// </summary>
    /// <param name="updateMipmaps">When the value is true, Unity recalculates mipmap levels, using mipmap level 0 as the source. The default value is true.</param>
    /// <param name="makeNoLongerReadable">When the value is true, Unity deletes the texture in CPU memory after it uploads it to the GPU, and sets Texture.isReadable|isReadable to false. The default value is false.</param>
    public void Apply([DefaultValue("true")] bool updateMipmaps, [DefaultValue("false")] bool makeNoLongerReadable)
    {
      if (!this.isReadable)
        throw this.CreateNonReadableException((Texture) this);
      this.ApplyImpl(updateMipmaps, makeNoLongerReadable);
    }

    [ExcludeFromDocs]
    public void Apply(bool updateMipmaps) => this.Apply(updateMipmaps, false);

    [ExcludeFromDocs]
    public void Apply() => this.Apply(true, false);

    public void SetPixelData<T>(T[] data, int mipLevel, int element, [DefaultValue("0")] int sourceDataStartIndex = 0)
    {
      if (sourceDataStartIndex < 0)
        throw new UnityException("SetPixelData: sourceDataStartIndex cannot be less than 0.");
      if (!this.isReadable)
        throw this.CreateNonReadableException((Texture) this);
      if (data == null || data.Length == 0)
        throw new UnityException("No texture data provided to SetPixelData.");
      this.SetPixelDataImplArray((Array) data, mipLevel, element, Marshal.SizeOf((object) data[0]), data.Length, sourceDataStartIndex);
    }

    public unsafe void SetPixelData<T>(
      NativeArray<T> data,
      int mipLevel,
      int element,
      [DefaultValue("0")] int sourceDataStartIndex = 0)
      where T : struct
    {
      if (sourceDataStartIndex < 0)
        throw new UnityException("SetPixelData: sourceDataStartIndex cannot be less than 0.");
      if (!this.isReadable)
        throw this.CreateNonReadableException((Texture) this);
      if (!data.IsCreated || data.Length == 0)
        throw new UnityException("No texture data provided to SetPixelData.");
      this.SetPixelDataImpl((IntPtr) data.GetUnsafeReadOnlyPtr<T>(), mipLevel, element, UnsafeUtility.SizeOf<T>(), data.Length, sourceDataStartIndex);
    }

    public unsafe NativeArray<T> GetPixelData<T>(int mipLevel, int element) where T : struct
    {
      if (!this.isReadable)
        throw this.CreateNonReadableException((Texture) this);
      if (mipLevel < 0 || mipLevel >= this.mipmapCount)
        throw new ArgumentException("The passed in miplevel " + mipLevel.ToString() + " is invalid. The valid range is 0 through " + (this.mipmapCount - 1).ToString());
      ulong num = element >= 0 && element < this.depth ? this.GetPixelDataOffset(this.mipmapCount, element) : throw new ArgumentException("The passed in element " + element.ToString() + " is invalid. The valid range is 0 through " + (this.depth - 1).ToString());
      ulong pixelDataOffset = this.GetPixelDataOffset(mipLevel, element);
      ulong length = this.GetPixelDataSize(mipLevel, element) / (ulong) UnsafeUtility.SizeOf<T>();
      if (length > (ulong) int.MaxValue)
        throw this.CreateNativeArrayLengthOverflowException();
      NativeArray<T> nativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<T>((void*) new IntPtr((long) this.GetImageDataPointer() + ((long) num * (long) element + (long) pixelDataOffset)), (int) length, Allocator.None);
      NativeArrayUnsafeUtility.SetAtomicSafetyHandle<T>(ref nativeArray, this.GetSafetyHandleForSlice(mipLevel, element));
      return nativeArray;
    }

    private static void ValidateIsNotCrunched(TextureCreationFlags flags)
    {
      if ((flags &= TextureCreationFlags.Crunch) != 0)
        throw new ArgumentException("Crunched Texture2DArray is not supported.");
    }

    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void GetSafetyHandleForSlice_Injected(
      int mipLevel,
      int element,
      out AtomicSafetyHandle ret);
  }
}
